var tileDict = Array("wall.png", "floor_12.png", "floor_12.png", "stairs_up.png", "stairs_down.png", "Wall_NS.png", "Wall_WE.png", "Wall_N.png", "Wall_W.png", "Wall_S.png", "Wall_E.png", "Corner_NE.png", "Corner_NW.png", "Corner_SW.png", "Corner_SE.png", "Cross.png", "Cross_N.png", "Cross_W.png", "Cross_S.png", "Cross_E.png", "Cross.png");
var charDict = Array("link-blue-walk.png", "link-blue-attack.png", "link-blue-defense.png", "link-blue-none.png");
var otherDict = Array("bat.png", "blurp.png", "skeleton.png");
var hudDict = Array("backplate.png", "face.png", "sword.png", "sheild.png", "heart_0.png", "heart_1.png", "heart_2.png", "heart_3.png", "heart_4.png");
var charImg = new Array();
var charSprite = new Array();
var otherSprite = new Array();
var tileImg = new Array();
var hudImg = new Array();

var player = new Player();
var other = new Array();

// array of all the levels in our game
var levels = new Array();//[new Level()];

// the current level index into our levels array
var currentLevel = 0;

// basic camera object
var camera = { x: 0, y: 0 };

var _loadTimer;
var _actionTimer;

TypeOfLevel = {
    Dungeon: false,
    Cave: true
};
var typeOfLevel = TypeOfLevel.Cave;

// handle keyboard controls
var keysDown = {};
addEventListener(
    "keydown",
    function(e) {
        for (var k in Keys) {
            if (Keys[k] == e.keyCode) {
                keysDown[e.keyCode] = true;
                if (e.preventDefault) { e.preventDefault(); }
                return true;
            }
        }
    },
    false);
addEventListener(
    "keyup",
    function(e) {
        for (var k in Keys) {
            if (Keys[k] == e.keyCode) {
                delete keysDown[e.keyCode];
                if (e.preventDefault) { e.preventDefault(); }
                return true;
            }
        }
    },
    false);

	if (!window.requestAnimationFrame) {
    window.requestAnimationFrame = (function() {
        return window.requestAnimationFrame ||
               window.webkitRequestAnimationFrame ||
               window.mozRequestAnimationFrame ||
               window.oRequestAnimationFrame ||
               window.msRequestAnimationFrame ||
               function(callback, element) { window.setTimeout(callback, 1000 / 60); };
		})();
	}

function putEnvToInitState() {
	// place the player at the up stair case
	var stairs = levels[currentLevel].dungeon.getStairs();
	player.pos.x = (stairs.up.x * tileSize) + tileSize / 2 - player.size.x / 2;
	player.pos.y = (stairs.up.y * tileSize) + tileSize / 2 - player.size.y / 2;
	
	levels[currentLevel].Init();
	
	var x;
	var y;
	var j = 0;
	
	for (var i = levels[currentLevel].dungeon.rooms.length-1; i >= 0; i--) {
	
		x = levels[currentLevel].dungeon.rooms[i].pos.x+levels[currentLevel].dungeon.rooms[i].size.x/2;
		y = levels[currentLevel].dungeon.rooms[i].pos.y+levels[currentLevel].dungeon.rooms[i].size.y/2;
	
		// Animals
		other[j] = new Animals();
		other[j].refOfSprite = otherSprite[j];
		other[j].setLife(1);
		
		other[j].pos.x = ((x) * tileSize) + tileSize / 2 - other[j].size.x / 2;
		other[j].pos.y = ((y) * tileSize) + tileSize / 2 - other[j].size.y / 2;
		
		j++;
		
		// Ennemies
		other[j] = new Ennemies();
		other[j].refOfSprite = otherSprite[j];
		other[j].setLife(1);
		other[j].setValueAttack(0.1);
			
		other[j].pos.x = ((x) * tileSize) + tileSize / 2 - other[j].size.x / 2;
		other[j].pos.y = ((y) * tileSize) + tileSize / 2 - other[j].size.y / 2;	
		
		j++;	

		// EnnemiesAStar
		other[j] = new EnnemiesAStar();
		other[j].refOfSprite = otherSprite[j];
		other[j].setLife(1);
		other[j].setValueAttack(0.25);
		other[j].setRadius(5);
			
		other[j].pos.x = ((x) * tileSize) + tileSize / 2 - other[j].size.x / 2;
		other[j].pos.y = ((y) * tileSize) + tileSize / 2 - other[j].size.y / 2;	
		
		j++;		
	}
}
function loadImg() {
	for (var i = charDict.length-1; i >= 0; i--) {
        charSprite[i] = new Sprite("sprites/" + charDict[i]);
    }
	
	var j = 0;
	for (var i = levels[currentLevel].dungeon.rooms.length-1; i >= 0; i--) {
		otherSprite[j] = new Sprite("sprites/" + otherDict[0]);
		j++;
		otherSprite[j] = new Sprite("sprites/" + otherDict[1]);
		j++;
		otherSprite[j] = new Sprite("sprites/" + otherDict[2]);
		j++;
	}
	
    for (var i = 0; i < tileDict.length; i++) {
        tileImg[i] = new Image();
        tileImg[i].src = "tiles/" + tileDict[i];
        tileImg[i].onload = function() {
            loaded++;
        }
    } 

	for (var i = 0; i < hudDict.length; i++) {
        hudImg[i] = new Image();
        hudImg[i].src = "systems/" + hudDict[i];
        hudImg[i].onload = function() {
            loaded++;
        }
    }	
}

function GenerateEnv() {
	//level
	levels[0] = new Level(typeOfLevel);
		
	// player
	player = new Player();
	player.setLife(5*4);
	player.setValueAttack(1);
	player.setRadius(10);
}

function loadAll() {
    if (loaded == tileDict.length + charDict.length + otherSprite.length + hudImg.length) {
        clearInterval(_loadTimer);
		
		putEnvToInitState();

        window.requestAnimationFrame(MainLoop, document.getElementById('myCanvas'));
    }
}

function ResetGame() {
    levels = [new Level(typeOfLevel)];
    currentLevel = 0;
    camera = { x: 0, y: 0 };
    keysDown = {};
}

function Update(elapsed) {
    var change = levels[currentLevel].update(elapsed, keysDown);

    if (change == -1) {
        if (currentLevel > 0) {
            currentLevel--;
			player.pos.x = levels[currentLevel].playerPos.x;
			player.pos.y = levels[currentLevel].playerPos.y;
			
        }
    }
    else if (change == 1) {
        if (currentLevel == levels.length - 1) {
            levels.push(new Level(typeOfLevel));
        }
		levels[currentLevel].playerPos.x = player.pos.x;
		levels[currentLevel].playerPos.y = player.pos.y;
		
        currentLevel++;
		
		putEnvToInitState();
    }

    var cx = player.pos.x + player.size.x / 2;
    var cy = player.pos.y + player.size.y / 2;
    camera.x = Math.floor(cx - canvas.width / 2);
    camera.y = Math.floor(cy - canvas.height / 2);
	
	player.update(elapsed, keysDown);
	levels[currentLevel].updateEntity(elapsed, keysDown);
}
function DrawHUD() {
	context.drawImage(hudImg[0],0,0);
	context.drawImage(hudImg[1],10,10);
	context.font = "bold 12px sans-serif";
	context.fillStyle = "white";
	context.fillText("Level : " + currentLevel + "", 355, 25);	
	
	var numberOfHeart = Math.ceil(player.maxLife/4);
	for(var i=1 ; i <= numberOfHeart ; i++) {
		if(player.life >= i*4)
			context.drawImage(hudImg[8],80+i*18,(80/2)-(16/2));
		else if(player.life >= (i-1)*4+3)
			context.drawImage(hudImg[7],80+i*18,(80/2)-(16/2));
		else if(player.life >= (i-1)*4+2)
			context.drawImage(hudImg[6],80+i*18,(80/2)-(16/2));
		else if(player.life >= (i-1)*4+1)
			context.drawImage(hudImg[5],80+i*18,(80/2)-(16/2));
		else
			context.drawImage(hudImg[4],80+i*18,(80/2)-(16/2));
	}
	
	context.fillText("A:", 300-10, 37);
	context.drawImage(hudImg[2],300, 25);
	context.fillText("D:", 300-10, 57);
	context.drawImage(hudImg[3],300, 45);
}

function Draw() {
	context = canvas.getContext('2d');
    canvas.width = canvas.width; // clears the canvas 

    // draw the current level
    levels[currentLevel].draw(canvas, context, camera);
	// draw env
	player.draw(canvas, context, camera);
	levels[currentLevel].drawEntity(canvas, context, camera);
	// draw minimap
	levels[currentLevel].drawMiniMap(canvas, context, camera);
	
	DrawHUD();
}

var prevTime = Date.now();
function MainLoop() {
    var time = Date.now();
    var delta = (time - prevTime) / 1000.0;
    prevTime = time;

    Update(delta);

    Draw();

    window.requestAnimationFrame(MainLoop, document.getElementById('myCanvas'));
}

function MainLoopAction() {
}

function Initialize() {
    canvas = document.getElementById('myCanvas');
	context = canvas.getContext('2d');
    canvas.width = window.innerWidth -1;
    canvas.height = window.innerHeight  -1;
	
	GenerateEnv();
	loadImg();
	
    _loadTimer = setInterval(loadAll, 100);
}